home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / ttxsame / place.c next >
Encoding:
C/C++ Source or Header  |  1997-09-09  |  11.0 KB  |  522 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  PLACE.C
  9.  *
  10.  *  PlaceRexxCommand()
  11.  *
  12.  *  Send an AREXX command according to arguments and RexxHostName
  13.  */
  14.  
  15. #include "rexx/rexx.h"
  16.  
  17. void ClearDiceRexxPort(MsgPort *);
  18. void RexxReply(void *, long, char *);
  19.  
  20. static MsgPort RexxPort;            /*    master port    */
  21. static char    *RexxPortName = "REXX";      /*  master port name    */
  22.  
  23. static short    GlobalFlag;
  24. static short    MasterPortValid;
  25.  
  26. static List    RexxWIPList;
  27. static List    RexxRIPList;
  28. static List    RexxAuxPortList;
  29. static short    RexxPortInitialized;
  30.  
  31. short    RexxSigBit;    /*  master signal   */
  32.  
  33. __autoinit
  34. static void
  35. __dice_rexx_init()
  36. {
  37.     /*
  38.      *    initialize the list that tracks rexx requests sent
  39.      */
  40.  
  41.     RexxWIPList.lh_Head = (Node *)&RexxWIPList.lh_Tail;
  42.     RexxWIPList.lh_TailPred = (Node *)&RexxWIPList.lh_Head;
  43.  
  44.     /*
  45.      *    initialize the list that tracks rexx requests received
  46.      */
  47.  
  48.     RexxRIPList.lh_Head = (Node *)&RexxRIPList.lh_Tail;
  49.     RexxRIPList.lh_TailPred = (Node *)&RexxRIPList.lh_Head;
  50.  
  51.     /*
  52.      *    initialize the auxillary port list and add our master node to
  53.      *    it.
  54.      */
  55.  
  56.     RexxAuxPortList.lh_Head = (Node *)&RexxAuxPortList.lh_Tail;
  57.     RexxAuxPortList.lh_TailPred = (Node *)&RexxAuxPortList.lh_Head;
  58.  
  59.     /*
  60.      *    Get our master signal and create master port
  61.      */
  62.  
  63.     RexxSigBit = AllocSignal(-1);
  64.  
  65.     if (RexxHostName)
  66.     CreateDiceRexxPort(NULL, RexxHostName);
  67.  
  68.     RexxPortInitialized = 1;
  69. }
  70.  
  71. /*
  72.  *  The exit code can be called at any point... there might be multiple
  73.  *  messages queued, in the queue, or in processing.  We must do the
  74.  *  following items in order:
  75.  *
  76.  *    (1) prevent any further messages from being received
  77.  *    (2) return any messages queued-in or in processing
  78.  *    (3) wait for any outgoing messages to be returned
  79.  */
  80.  
  81. __autoexit
  82. static void
  83. __dice_rexx_exit()
  84. {
  85.     if (RexxPortInitialized) {
  86.     RexxPortNode *rp;
  87.  
  88.     /*
  89.      *  prevent further messages from being received
  90.      */
  91.  
  92.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)rp->rp_Node.ln_Succ) {
  93.         if (rp->rp_IsPublic) {
  94.         RemPort(rp->rp_MsgPort);
  95.         rp->rp_IsPublic = 0;
  96.         }
  97.     }
  98.  
  99.     /*
  100.      *  return any messages in processing or queued-in
  101.      */
  102.  
  103.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)rp->rp_Node.ln_Succ)
  104.         ClearDiceRexxPort(rp->rp_MsgPort);
  105.  
  106.     /*
  107.      *  wait for replies from rexx commands we have sent.  Since we
  108.      *  have cleared all other messages, no lockout conditions can
  109.      *  occur at this point.
  110.      */
  111.  
  112.     {
  113.         RexxIPNode *rip;
  114.  
  115.         while (rip = (RexxIPNode *)RemHead(&RexxWIPList)) {
  116.         if (rip->rip_Returned == 0) {
  117.             while (((Message *)rip->rip_RexxMsg)->mn_Node.ln_Type != NT_REPLYMSG)
  118.             Wait(1 << RexxSigBit);
  119.             Forbid();
  120.             Remove(&rip->rip_RexxMsg->rm_Node.mn_Node);
  121.             Permit();
  122.             rip->rip_Returned = 1;
  123.         }
  124.         ClearRexxMsg(rip->rip_RexxMsg, 1);
  125.         DeleteRexxMsg(rip->rip_RexxMsg);
  126.         }
  127.     }
  128.  
  129.     /*
  130.      *  Delete the ports.  Since we have cleared rp_IsPublic it will
  131.      *  not try to RemPort() them again.
  132.      */
  133.  
  134.     while ((rp = (RexxPortNode *)RexxAuxPortList.lh_Head) != (RexxPortNode *)&RexxAuxPortList.lh_Tail)
  135.         DeleteDiceRexxPort(rp->rp_MsgPort);
  136.  
  137.     /*
  138.      *  Free our master signal
  139.      */
  140.  
  141.     FreeSignal(RexxSigBit);
  142.     RexxPortInitialized = 0;
  143.     }
  144. }
  145.  
  146. long
  147. PlaceRexxCommandDirect(port, remoteName, arg, pres, pec)
  148. MsgPort *port;
  149. char *remoteName;
  150. char *arg;
  151. char **pres;
  152. long *pec;
  153. {
  154.     char *rpn = RexxPortName;
  155.     long r;
  156.  
  157.     RexxPortName = remoteName;
  158.     r = PlaceRexxCommand(port, arg, pres, pec);
  159.     RexxPortName = rpn;
  160.     return(r);
  161. }
  162.  
  163. long
  164. PlaceRexxCommand(port, arg, pres, pec)
  165. MsgPort *port;
  166. char *arg;
  167. char **pres;
  168. long *pec;
  169. {
  170.     RexxIPNode rip;
  171.     long rc = -2;
  172.  
  173.     if (port == NULL) {
  174.     if (MasterPortValid == 0)
  175.         return(-1);
  176.     port = &RexxPort;
  177.     }
  178.  
  179.     if (pres)
  180.     *pres = NULL;
  181.     if (pec)
  182.     *pec = 0;
  183.  
  184.  
  185.     if (RexxSysBase) {
  186.     rc = -1;
  187.  
  188.     if (rip.rip_RexxMsg = CreateRexxMsg(port, ((RexxHostName) ? RexxHostName : "UNKNOWN"), port->mp_Node.ln_Name)) {
  189.         MsgPort *arexxPort;
  190.  
  191.         rip.rip_RexxMsg->rm_Node.mn_Node.ln_Name = "REXX";
  192.         rip.rip_RexxMsg->rm_Action = RXCOMM;
  193.         if (pres) rip.rip_RexxMsg->rm_Action |= RXFF_RESULT;
  194.         ARG0(rip.rip_RexxMsg) = CreateArgstring(arg,strlen(arg));
  195.  
  196.         AddHead(&RexxWIPList, &rip.rip_Node);
  197.         rip.rip_Returned = 0;
  198.         rip.rip_RexxPort = port;
  199.  
  200.         Forbid();
  201.         if (arexxPort = (MsgPort *)FindPort(RexxPortName)) {
  202.         PutMsg(arexxPort, (Message *)rip.rip_RexxMsg);
  203.         Permit();
  204.  
  205.         while (rip.rip_Returned == 0) {
  206.             RexxPortNode *rp;
  207.  
  208.             /*
  209.              *    Since this is the only wait on this signal there
  210.              *    can be no lockout condition.
  211.              */
  212.  
  213.             Wait(1 << RexxSigBit);
  214.             for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)(rp->rp_Node.ln_Succ))
  215.             ProcessRexxCommands(rp->rp_MsgPort);
  216.         }
  217.         } else {
  218.         Permit();
  219.         }
  220.         Remove(&rip.rip_Node);
  221.  
  222.         /*
  223.          *    Process result / return code here if rip.rip_Returned == 0
  224.          *    then we were not able to dispatch the message
  225.          */
  226.  
  227.         if (rip.rip_Returned) {
  228.         if ((rc = rip.rip_RexxMsg->rm_Result1) == 0) {
  229.             if (rip.rip_RexxMsg->rm_Result2) {
  230.             if (pres)
  231.                 *pres = strdup((char *)rip.rip_RexxMsg->rm_Result2);
  232.             DeleteArgstring((UBYTE *)rip.rip_RexxMsg->rm_Result2);
  233.             }
  234.         } else {
  235.             if (pec)
  236.             *pec = (long)rip.rip_RexxMsg->rm_Result2;
  237.         }
  238.         }
  239.         ClearRexxMsg(rip.rip_RexxMsg, 1);
  240.         DeleteRexxMsg(rip.rip_RexxMsg);
  241.     }
  242.     }
  243.     return(rc);
  244. }
  245.  
  246. void
  247. ProcessRexxCommands(port)
  248. MsgPort *port;
  249. {
  250.     RexxMsg *msg;
  251.  
  252.     if (port == NULL) {
  253.     RexxPortNode *rp;
  254.  
  255.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)(rp->rp_Node.ln_Succ))
  256.         ProcessRexxCommands(rp->rp_MsgPort);
  257.     return;
  258.     }
  259.  
  260.     while (msg = (struct RexxMsg *)GetMsg(port)) {
  261.     if ((msg->rm_Node.mn_Node.ln_Type == NT_MESSAGE) && IsRexxMsg(msg)) {
  262.         RexxIPNode rip;
  263.         char *str = NULL;
  264.         long rc;
  265.  
  266.         rip.rip_RexxMsg = msg;
  267.         rip.rip_RexxPort = port;
  268.         AddTail(&RexxRIPList, &rip.rip_Node);
  269.         rc = DoRexxCommand(msg, port, ARG0(msg), &str);
  270.         Remove(&rip.rip_Node);
  271.         RexxReply(msg, rc, str);
  272.     } else {
  273.         RexxIPNode *rip;
  274.  
  275.         for (rip = (RexxIPNode *)RexxWIPList.lh_Head; rip->rip_Node.ln_Succ; rip = (RexxIPNode *)rip->rip_Node.ln_Succ) {
  276.         if (msg == rip->rip_RexxMsg) {
  277.             rip->rip_Returned = 1;
  278.             break;
  279.         }
  280.         }
  281.     }
  282.     }
  283. }
  284.  
  285. /*
  286.  *  Create a global DICE rexx port
  287.  */
  288.  
  289. short
  290. CreateGlobalDiceRexxPort(port, name)
  291. MsgPort *port;
  292. char *name;
  293. {
  294.     short r;
  295.  
  296.     GlobalFlag = 1;
  297.     r = CreateDiceRexxPort(port, name);
  298.     GlobalFlag = 0;
  299.  
  300.     return(r);
  301. }
  302.  
  303. /*
  304.  *  Create an application DICE rexx port
  305.  */
  306.  
  307. short
  308. CreateDiceRexxPort(port, name)
  309. MsgPort *port;
  310. char *name;
  311. {
  312.     RexxPortNode *rp;
  313.     short pno;
  314.     short isPublic;
  315.     short allocSize;
  316.  
  317.     if (port == NULL) {
  318.     port = &RexxPort;
  319.     MasterPortValid = 1;
  320.     }
  321.  
  322.     if (name == NULL) {
  323.     name = "PRIVATE-REXX-PORT";
  324.     isPublic = 0;
  325.     } else {
  326.     isPublic = 1;
  327.     }
  328.     allocSize = sizeof(RexxPortNode) + strlen(name) + 4;
  329.  
  330.     rp = AllocMem(allocSize, MEMF_PUBLIC|MEMF_CLEAR);
  331.  
  332.     rp->rp_Node.ln_Type = allocSize;
  333.     rp->rp_MsgPort = port;
  334.     rp->rp_IsPublic = isPublic;
  335.     AddTail(&RexxAuxPortList, &rp->rp_Node);
  336.  
  337.     port->mp_Node.ln_Name = (char *)(rp + 1);
  338.  
  339.     port->mp_Node.ln_Type = NT_MSGPORT;
  340.     port->mp_Node.ln_Pri = 1;
  341.     port->mp_Flags = PA_SIGNAL;
  342.     port->mp_SigBit = RexxSigBit;
  343.     port->mp_SigTask = FindTask(NULL);
  344.     port->mp_MsgList.lh_Head = (Node *)&port->mp_MsgList.lh_Tail;
  345.     port->mp_MsgList.lh_TailPred = (Node *)&port->mp_MsgList.lh_Head;
  346.  
  347.     /*
  348.      *    Give the port a real name according to AREXX semantics,
  349.      *    portname.NN (01-99)
  350.      */
  351.  
  352.     Forbid();
  353.  
  354.     if (GlobalFlag || isPublic == 0) {
  355.     strcpy(port->mp_Node.ln_Name, name);
  356.     if (isPublic && FindPort(port->mp_Node.ln_Name))
  357.         pno = -1;
  358.     else
  359.         pno = 0;
  360.     } else {
  361.     for (pno = 1; pno < 100; ++pno) {
  362.         char buf[4];
  363.         strcpy(buf, ".00");
  364.         buf[1] += pno / 10;
  365.         buf[2] += pno % 10;
  366.         strcpy(port->mp_Node.ln_Name, name);
  367.         strcat(port->mp_Node.ln_Name, buf);
  368. /*        sprintf(port->mp_Node.ln_Name, "%s.%02d", name, pno); */
  369.         if (FindPort(port->mp_Node.ln_Name) == NULL)
  370.         break;
  371.     }
  372.     if (pno == 100)
  373.         pno = -1;
  374.     }
  375.  
  376.     if (isPublic)
  377.     AddPort(port);
  378.  
  379.     if (pno < 0)
  380.     DeleteDiceRexxPort(port);
  381.     else if (port == (MsgPort *)&RexxPort && RexxHostName == NULL)
  382.     RexxHostName = port->mp_Node.ln_Name;
  383.  
  384.     Permit();
  385.  
  386.     return(pno);
  387. }
  388.  
  389. /*
  390.  *  Delete a DICE rexx port.  Note that there can be no outgoing messages
  391.  *  in-progress for this port for this command to work properly.
  392.  */
  393.  
  394. void
  395. DeleteDiceRexxPort(port)
  396. MsgPort *port;
  397. {
  398.     /*
  399.      *    check if valid port, remove RexxPortNode if found
  400.      */
  401.  
  402.     {
  403.     RexxPortNode *rp;
  404.  
  405.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)rp->rp_Node.ln_Succ) {
  406.         if (rp->rp_MsgPort == port) {
  407.         Remove(&rp->rp_Node);
  408.         if (rp->rp_IsPublic)
  409.             RemPort(port);
  410.         FreeMem(rp, rp->rp_Node.ln_Type);
  411.         break;
  412.         }
  413.     }
  414.     if (rp == NULL)
  415.         return;
  416.     }
  417.  
  418.     ClearDiceRexxPort(port);
  419.  
  420.     /*
  421.      *    clear port info
  422.      */
  423.  
  424.     clrmem(port, sizeof(MsgPort));
  425.  
  426.     if (port == (MsgPort *)&RexxPort)
  427.     MasterPortValid = 0;
  428. }
  429.  
  430. void
  431. ClearDiceRexxPort(port)
  432. MsgPort *port;
  433. {
  434.     /*
  435.      *    kill any received messages that are in progress
  436.      */
  437.  
  438.     {
  439.     RexxIPNode *rip;
  440.     RexxIPNode *rip_next;
  441.  
  442.     for (rip = (RexxIPNode *)RexxRIPList.lh_Head; rip->rip_Node.ln_Succ; rip = rip_next) {
  443.         rip_next = (RexxIPNode *)rip->rip_Node.ln_Succ;
  444.         if (rip->rip_RexxPort == port) {
  445.         Remove(&rip->rip_Node);
  446.         RexxReply(rip->rip_RexxMsg, 30, NULL);
  447.         }
  448.     }
  449.     }
  450.  
  451.  
  452.     /*
  453.      *    clear out any messages pending on the port
  454.      */
  455.  
  456.     {
  457.     RexxMsg *msg;
  458.  
  459.     while (msg = (RexxMsg *)GetMsg(port)) {
  460.         if ((msg->rm_Node.mn_Node.ln_Type == NT_MESSAGE) && IsRexxMsg(msg)) {
  461.         RexxReply(msg, 30, NULL);
  462.         } else {
  463.         RexxIPNode *rip;
  464.  
  465.         for (rip = (RexxIPNode *)RexxWIPList.lh_Head; rip->rip_Node.ln_Succ; rip = (RexxIPNode *)rip->rip_Node.ln_Succ) {
  466.             if (msg == rip->rip_RexxMsg) {
  467.             rip->rip_Returned = 1;
  468.             break;
  469.             }
  470.         }
  471.         }
  472.     }
  473.     }
  474. }
  475.  
  476. void
  477. RexxReply(vmsg, res1, str)
  478. void *vmsg;
  479. long res1;
  480. char *str;
  481. {
  482.     RexxMsg *msg = vmsg;
  483.  
  484.     if (msg->rm_Result1 = res1) {
  485.     msg->rm_Result2 = NULL;
  486.     } else {
  487.     if (str)
  488.         msg->rm_Result2 = (long)CreateArgstring(str, strlen(str));
  489.     else
  490.         msg->rm_Result2 = NULL;
  491.     }
  492.     ReplyMsg((Message *)msg);
  493. }
  494.  
  495. /*
  496.  *  Obtain the fully qualified name of an application port (name.xx) and
  497.  *  return an integer.    Returns -1 if the port does not contain a .xx
  498.  *  extension.
  499.  */
  500.  
  501. int
  502. GetDiceRexxPortSlot(port, pname)
  503. MsgPort *port;
  504. char **pname;
  505. {
  506.     int slotNo = -1;
  507.     char *ptr;
  508.  
  509.     if (port == NULL)
  510.     port = &RexxPort;
  511.     if (ptr = strrchr(port->mp_Node.ln_Name, '.')) {
  512.     char *tmp;
  513.  
  514.     slotNo = strtol(ptr + 1, &tmp, 10);  /* must be base 10 re: '.01'... */
  515.     if (tmp == ptr)
  516.         slotNo = -1;
  517.     }
  518.     if (pname)
  519.     *pname = port->mp_Node.ln_Name;
  520.     return(slotNo);
  521. }
  522.